#include <iostream>
using std::cout;
using std::endl;

class Singleton{
    friend class AutoRelease;

public:
    static Singleton* getInstance(){
        if(_pInstance == nullptr){
            _pInstance = new Singleton();
            cout << "[Memory] Singleton created at: " << _pInstance << endl; // 对象地址
            cout << "[Memory] _pInstance pointer address: " << &_pInstance 
     << ", pointing to: " << _pInstance << endl;
            static AutoRelease ar(_pInstance);
//            cout << "[Memory] AutoRelease ar created at: " << &ar << endl; // 对象地址
        }
        cout << "[Call] getInstance() return: " << _pInstance << endl;      // 返回地址
        return _pInstance;
    }

    void print() { 
        cout << "[Call] print() @ this=" << this << endl;                   // this指针
        cout << "Singleton working" << endl; 
    }

private:
    class AutoRelease{
    public:
        AutoRelease(Singleton* ptr)
            :_ptr(ptr){
                cout << "[Memory] AutoRelease ar constructed at: " << &_ptr << endl;
                cout << "[Memory] AutoRelease constructed, managing: " << _ptr << endl;
            }

        ~AutoRelease(){
            if(_ptr != nullptr){
                cout << "[Memory] Deleting Singleton @ " << _ptr << endl;   // 释放地址
                delete _ptr;
                _ptr = nullptr;
            }
        }

        Singleton* operator->(){
            cout << "[Operator] AutoRelease-> called, return: " << _ptr << endl;
            return _ptr;
        }

        Singleton& operator*(){
            cout << "[Operator] AutoRelease* called, return @" << _ptr << endl;
            return *_ptr;
        }

    private:
        Singleton* _ptr;
    };
    static Singleton* _pInstance; 

    Singleton() { 
        cout << "[Memory] Singleton constructor @ " << this << endl;        // 构造地址
    }
    ~Singleton() { 
        cout << "[Memory] Singleton destructor @ " << this << endl;         // 析构地址
    }

    Singleton(const Singleton&) = delete;
    Singleton operator=(const Singleton&) = delete;
};

Singleton* Singleton::_pInstance = nullptr;

void test(){
    cout << "\n----- Test Start -----" << endl;
    Singleton::getInstance()->print();
    Singleton::getInstance()->print();
    cout << "----- Test End -----\n" << endl;
}

int main() {
    cout << "[Program] Main started" << endl;
    test();
    cout << "[Program] Main finished" << endl;
    return 0;
}
